package cs2340.spring13.team3.wheresmystuff.presenters;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.DeserializationConfig;

import cs2340.spring13.team3.wheresmystuff.model.User;
import cs2340.spring13.team3.wheresmystuff.model.ServerObject;
import cs2340.spring13.team3.wheresmystuff.support.JSONMessage;

/**
 * @author Tim Swihart <email obscured since this file is public>
 * @version 0.3
 * @since 2013-03-04
 */
public class LoginManager {
	private static final LoginManager loginManager = new LoginManager();

	public static LoginManager getInstance() {
		return loginManager;
	}

	private User user;
	private static String loginUrl;
	private static String registerUrl;
	private String error;
	private DefaultHttpClient http;

	private LoginManager() {
		// Using http so I can inspect traffic and verify that things are
		// working.
		LoginManager.loginUrl = "https://immense-temple-7838.herokuapp.com/login";
		LoginManager.registerUrl = "https://immense-temple-7838.herokuapp.com/users/new";
		this.setUser(null);
		this.http = new DefaultHttpClient();
		ServerObject.setHttpClient(http);
		ServerObject.setObjectMapper(new ObjectMapper());
	}

	/**
	 * @param email
	 * @param password
	 * @return true if the login was successful. False if unsuccessful, and the
	 *         error message is set accordingly
	 * @throws IOException
	 *             for possible network errors
	 */
	public boolean attemptLogin(String email, String password)
			throws IOException {
		// connect to server, check credentials, take user if it works
		HttpPost loginPost = new HttpPost(loginUrl);

		List<NameValuePair> nvp = new ArrayList<NameValuePair>();
		nvp.add(new BasicNameValuePair("email", email));
		nvp.add(new BasicNameValuePair("password", password));
		loginPost.setEntity(new UrlEncodedFormEntity(nvp));

		HttpResponse response = http.execute(loginPost);

		InputStream is = response.getEntity().getContent();

		ObjectMapper mapper = new ObjectMapper();
		JSONMessage msg = new JSONMessage(mapper.readValue(is, JsonNode.class));
		if (msg.getErr().length() > 0 && msg.getErr() != "null") {
			this.setError(msg.getErr());
			return false;
		} else {
			this.setUser(new User(mapper, msg.getObj()));
			return true;
		}
	}

	/**
	 * Attempt to register a new account using the given information. If the
	 * registration attempt fails then the login manager's error value will be
	 * set
	 * 
	 * @param email
	 * @param password
	 * @return boolean whether or not the attempt succeeded
	 * @throws IOException
	 */
	public boolean attemptRegister(String email, String password)
			throws IOException {
		// connect to server, check credentials, take user if it works
		DefaultHttpClient hc = new DefaultHttpClient();
		this.http = hc;
		HttpPost loginPost = new HttpPost(registerUrl);

		List<NameValuePair> nvp = new ArrayList<NameValuePair>();
		nvp.add(new BasicNameValuePair("email", email));
		nvp.add(new BasicNameValuePair("password", password));
		loginPost.setEntity(new UrlEncodedFormEntity(nvp));

		HttpResponse response = hc.execute(loginPost);

		InputStream is = response.getEntity().getContent();

		ObjectMapper mapper = new ObjectMapper();
		mapper.configure(
				DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		JSONMessage msg = new JSONMessage(mapper.readValue(is, JsonNode.class));
		if (msg.getErr().length() > 0 && msg.getErr() != "null") {
			this.setError(msg.getErr());
			return false;
		} else {
			this.setUser(new User(mapper, msg.getObj()));
			return true;
		}
	}

	public User register(String email, String password) {
		return null;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String getError() {
		return error;
	}

	public void setError(String error) {
		this.error = error;
	}

	public DefaultHttpClient getHttpClient() {
		return http;
	}

}